
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;

using Swaf;
using Swaf.Container;

namespace Swaf.Crypto
{
	/// <summary>
	/// Summary description for RijndaelCryptoHandler.
	/// </summary>
	public class RijndaelCryptoHandler : ICryptoHandler
	{
		#region ICryptoHandler Members

		public object[] generateKey()
		{
			Rijndael rij = new RijndaelManaged();
			rij.GenerateIV();
			rij.GenerateKey();
			return new object[]{rij.IV, rij.Key};
		}

		public ICrypto startCryptoSession(object[] key)
		{
			Rijndael rij = new RijndaelManaged();
			rij.IV = (byte[])key[0];
			rij.Key = (byte[])key[1];
			return new RijndaelCrypto(rij);
		}

		#endregion

		protected class RijndaelCrypto : ICrypto
		{
			protected Rijndael m_rij;
			protected ICryptoTransform m_encryptor;
			protected ICryptoTransform m_decryptor;

			public RijndaelCrypto(Rijndael rij)
			{
				m_rij = rij;
			}

			#region ICrypto Members

			public string encrypt(string info)
			{
				return Convert.ToBase64String(this.encrypt(Encoding.UTF8.GetBytes(info)));
			}

			public byte[] encrypt(byte[] info)
			{
				lock(this)
				{
					if(m_encryptor == null)
						m_encryptor = m_rij.CreateEncryptor();
				}
				lock(m_encryptor)
				{
					MemoryStream tvOutput = new MemoryStream();
					CryptoStream tvCryptStream = new CryptoStream(tvOutput,	m_encryptor,CryptoStreamMode.Write);
					tvCryptStream.Write(info, 0, info.Length);
					tvCryptStream.FlushFinalBlock();

					return tvOutput.ToArray();
				}
			}

			public string decrypt(string info)
			{
				return Encoding.UTF8.GetString(this.decrypt(Convert.FromBase64String(info)));
			}

			public byte[] decrypt(byte[] info)
			{
				lock(this)
				{
					if(m_decryptor == null)
						m_decryptor = m_rij.CreateDecryptor();
				}

				lock(m_decryptor)
				{
					MemoryStream tvOutput = new MemoryStream();
					CryptoStream tvCryptStream = new CryptoStream(tvOutput, m_decryptor, CryptoStreamMode.Write);
					tvCryptStream.Write(info, 0, info.Length);
					tvCryptStream.FlushFinalBlock();

					return tvOutput.ToArray();
				}
			}


			public Stream createCryptoStream(Stream source)
			{
				if(source.CanWrite)
				{
					//if(m_encryptor == null)
					//	m_encryptor = m_rij.CreateEncryptor();
					return new CryptoStream(source, m_rij.CreateEncryptor(), CryptoStreamMode.Write);
				}
				else
				{
					//if(m_decryptor == null)
					//	m_decryptor = m_rij.CreateDecryptor();
					return new CryptoStream(source, m_rij.CreateDecryptor(), CryptoStreamMode.Read);
				}
			}

			#endregion

		}

	}
}
